package com.cqrt.service.impl;


import cn.hutool.core.util.ObjectUtil;
import com.cqrt.constant.RTErrorCodeEnum;
import com.cqrt.constant.RTPlmConstant;
import com.cqrt.dto.ImportProjectDTO;
import com.cqrt.mapper.RTProjectMapper;
import com.cqrt.service.HistoryDataImportService;

import com.cqrt.util.BeanMappers;
import com.cqrt.util.ExcelParser;
import com.cqrt.util.ProjectCodeGenerator;
import com.cqrt.util.WorkdayCalculator;
import com.hustcad.plm.pdm.core.context.TyppmUser;
import com.hustcad.plm.rpm.entityconvert.plan.ActiveTreeDTOConvert;
import com.hustcad.plm.rpm.model.dto.active.PlusTaskSaveDTO;
import com.hustcad.plm.rpm.model.dto.active.TyppmActiveTreeDTO;
import com.hustcad.plm.rpm.model.dto.admin.TyppmProjectDTO;
import com.hustcad.plm.rpm.model.entity.plan.TyppmPlan;
import com.hustcad.plm.rpm.model.vo.admin.ProjectVO;
import com.hustcad.plm.rpm.service.forpdm.admin.ProjectServiceForPdm;
import com.hustcad.plm.rpm.service.plan.TyppmGanttChartService;
import com.hustcad.plm.rpm.service.plan.TyppmPlanActiveService;
import com.hustcad.plm.rpm.util.beanmapper.BeanMapper;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.service.snow.SnowflakeIdComponent;
import com.ty.basic.session.TyAccountContext;
import com.ty.basic.utils.excel.converter.ExcelToList;
import com.ty.ppm.model.dto.active.ActiveTreeDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.ty.basic.utils.excel.converter.ExcelToList.getWorkbook;


@Service
@Slf4j
//@Transactional(rollbackFor = Exception.class)
public class HistoryDataImportServiceImpl implements HistoryDataImportService {

    @Resource
    private ProjectServiceForPdm projectServiceForPdm;
    @Resource
    private RTProjectMapper rtProjectMapper;
    @Resource
    private RTProjectServiceImpl rtProjectServiceImpl;
    @Resource
    private SnowflakeIdComponent snowflakeIdComponent;
    @Resource
    private TyppmGanttChartService ganttChartService;

    @Resource
    private ProjectCodeGenerator projectCodeGenerator;
    @Resource
    private ActiveTreeDTOConvert activeTreeDTOConvert;
    @Resource
    private BeanMappers beanMappers;
    @Resource
    private TyppmPlanActiveService planActiveService;


    @Override
    public void importAnnualProject(MultipartFile file) {
        //读取基础数据
        Map<String, String> fieldMap = ExcelToList.getExcelPropertySettingMapByClass(ImportProjectDTO.class);
        Workbook workbook = getWorkbook(file);
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);
            for (Row row : sheet) {
                for (Cell cell : row) {
                    cell.setCellType(CellType.STRING);
                }
            }
        }
        List<ImportProjectDTO> importProcessDTOS = ExcelToList.excelToList(0, 0, workbook, ImportProjectDTO.class, fieldMap);
        List<ImportProjectDTO> filteredList = importProcessDTOS.stream().filter(ImportProjectDTO::isRowEmpty).collect(Collectors.toList());

        log.info("======导入数据开始======>>,{}",filteredList);

        Map<String, List<ImportProjectDTO>> prjMap = filteredList.stream().collect(
                Collectors.groupingBy(ImportProjectDTO::getProjectOrProductName));

        for (Map.Entry<String, List<ImportProjectDTO>> entry: prjMap.entrySet()) {

            ProjectVO projectVO = new ProjectVO();
            Map<String, List<String>> ibaMap = new HashMap<>();

            projectVO.setPhase("启动");
            BigInteger typeOID= rtProjectMapper.selectProjectTypeByName(entry.getValue().get(0).getSector());
            if(ObjectUtil.isNull(typeOID)){
                throw RTErrorCodeEnum.PROJECT_TYPE_NOT_EXIST.getException("项目类型不存在");
            }
            projectVO.setCompletionStatus(0);
            projectVO.setTypeOid(typeOID.toString());
            projectVO.setTypeOtype(TableTypeConstrant.TY_TYPE_OTYPE);
            projectVO.setCategory(entry.getValue().get(0).getSector());
            projectVO.setTypeLogicalIdentifier(entry.getValue().get(0).getSector());
            projectVO.setTypeName(entry.getValue().get(0).getSector());

            projectVO.setName(entry.getKey());
            projectVO.setProjectNumber( projectCodeGenerator.generateProjectCode());

            projectVO.setAdminUserDescription(TyAccountContext.getUser().getDescription());
            projectVO.setAdminUserName(TyAccountContext.getUser().getName());
            projectVO.setAdminUserOid(TyAccountContext.getUser().getOid().toString());
            projectVO.setAdminUserOtype(TyAccountContext.getUser().getOtype());
            projectVO.setOwnerDescription(TyAccountContext.getUser().getDescription());

//           projectVO.setOwnerName(TyAccountContext.getUser().getName());
//           projectVO.setOwnerOID(TyAccountContext.getUser().getOid().toString());

            //年度
            ibaMap.put("Year", Collections.singletonList(entry.getValue().get(0).getYear()));
            //大类/客户
            ibaMap.put("CategoryCustomer", Collections.singletonList(entry.getValue().get(0).getCategoryOrCustomer()));
            //开发类型
            ibaMap.put("DevelopmentType", Collections.singletonList(entry.getValue().get(0).getCategoryOrCustomer()));
            //产品类别
            ibaMap.put("ProductCategory", Collections.singletonList(entry.getValue().get(0).getCategoryOrCustomer()));
            //产品系列
            ibaMap.put("ProductSeries", Collections.singletonList(entry.getValue().get(0).getCategoryOrCustomer()));
            //项目开发令号
            ibaMap.put("ProjectDevelopmentOrder", Collections.singletonList(entry.getValue().get(0).getProjectDevelopmentNo()));
            //开发等级
            ibaMap.put("DevelopmentLevel", Collections.singletonList(entry.getValue().get(0).getDevelopmentLevel()));

            UserDO userDO = rtProjectMapper.selectUserByName(entry.getValue().get(0).getProjectManager());
            UserDO userDO1 = rtProjectMapper.selectUserByName(entry.getValue().get(0).getLeadDesigner());
            if(ObjectUtil.isNull(userDO) || ObjectUtil.isNull(userDO1)){
                throw RTErrorCodeEnum.USER_NOT_EXIST.getException("用户不存在");
            }
            List<TyppmUser> projectManagerList = Stream.of(userDO, userDO1) // 过滤null
                    .map(user -> {
                        TyppmUser typpmUser = new TyppmUser();
                        typpmUser.setOid(user.getOid().toString());
                        typpmUser.setName(user.getName());
                        typpmUser.setDescription(user.getDescription());
                        typpmUser.setOtype(user.getOtype());
                        return typpmUser;
                    })
                    .collect(Collectors.collectingAndThen(
                            Collectors.toMap(
                                    TyppmUser::getOid,  // key: oid
                                    Function.identity(), // value: 对象本身
                                    (existing, replacement) -> existing
                            ),
                            map -> new ArrayList<>(map.values())
                    ));
            //项目经理
            projectVO.setProjectManagerList(projectManagerList);
            //IBA属性
            projectVO.setIbaAttribute(ibaMap);
            projectVO.setStartDate(
                    LocalDate.parse(entry.getValue().get(0).getPlannedStartTime(), DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay());
            int size = entry.getValue().size()-1;
            projectVO.setFinishDate(
                    LocalDateTime.parse(Objects.requireNonNull(
                                                ExcelParser.getProjectEndDateWithTime((entry.getValue().get(size).getPlannedEndTime()))),
                                        WorkdayCalculator.DATE_TIME_FORMATTER));

            // 生成项目
            TyppmProjectDTO map = BeanMapper.map(projectVO, TyppmProjectDTO.class);
            map.setTypeOID(projectVO.getTypeOid());
            map.setTypeOTYPE(projectVO.getTypeOtype());
            map.setPercentWorkComplete((double) 0);
            map.setTypeLogicalIdentifier(projectVO.getTypeLogicalIdentifier());
            map.setTypeName(projectVO.getTypeName());

            TyppmProjectDTO typpmProjectDTO = this.projectServiceForPdm.insertProject(map);
            TyppmPlan plan = typpmProjectDTO.getPlan();

            List<PlusTaskSaveDTO> plusTaskSaveDTOS = new ArrayList<>();

            //生成计划
            int planSequence = 1;
            for (ImportProjectDTO importProjectDTO : entry.getValue()) {

                String plannedEndTime = importProjectDTO.getPlannedEndTime();
                String plannedStartTime = importProjectDTO.getPlannedStartTime();

                PlusTaskSaveDTO plusTaskSaveDTO = new PlusTaskSaveDTO();

                LocalDate endDate = LocalDate.parse(plannedEndTime, RTPlmConstant.DATE_FORMATTER);
                endDate = rtProjectServiceImpl.adjustToNextWorkday(endDate); // 关键调整
                LocalDateTime endDateTime = endDate.atTime(23, 59, 59); // 23:59:59
                String currentEndTime = RTPlmConstant.DATETIME_FORMATTER.format(endDateTime);

                LocalDate startTime = LocalDate.parse(plannedStartTime, RTPlmConstant.DATE_FORMATTER);
                startTime = rtProjectServiceImpl.adjustToNextWorkday(startTime); // 关键调整
                LocalDateTime startDateTime = startTime.atTime(0, 0, 0);
                String currentStartTime = RTPlmConstant.DATETIME_FORMATTER.format(startDateTime);

                plusTaskSaveDTO.setActive("1");
                plusTaskSaveDTO.setConstraintType("0");
                plusTaskSaveDTO.setCritical("0");
                plusTaskSaveDTO.setOutLineLevel("1");
                plusTaskSaveDTO.setOutLineNumber(String.valueOf(planSequence++));
                plusTaskSaveDTO.setLineNumber(plusTaskSaveDTO.getOutLineNumber());// 设置序号
                plusTaskSaveDTO.setName(importProjectDTO.getTaskName()); // 设置计划名称
                plusTaskSaveDTO.setEarlyFinish(currentEndTime); // 设置结束时间
                plusTaskSaveDTO.setFinishDate(currentEndTime); // 设置结束时间
                plusTaskSaveDTO.setWork("0");
                plusTaskSaveDTO.setPercentWorkComplete("0");

                //开始时间
                plusTaskSaveDTO.setEarlyStart(currentStartTime);
                plusTaskSaveDTO.setConstraintDate(currentStartTime);
                plusTaskSaveDTO.setStartDate(currentStartTime);

                if ((planSequence++)!=1){
                    plusTaskSaveDTO.setConstraintType("4");
                }
                // 计算工期（毫秒）并设置
                long durationMillis = WorkdayCalculator.calculateWorkdayDuration(
                        currentStartTime,
                        currentEndTime
                );
                plusTaskSaveDTO.setDuration(String.valueOf(durationMillis));


                plusTaskSaveDTO.setOid(snowflakeIdComponent.getInstance().nextId().toString());
                plusTaskSaveDTO.setOtype( TableTypeConstrant.TY_PLAN_ACTIVITY_OTYPE);
                plusTaskSaveDTO.setParentOID(plan.getOid());
                plusTaskSaveDTO.setParentOTYPE(RTPlmConstant.PLAN_TYPE);
                plusTaskSaveDTO.setPercentWorkComplete("0");
                //plusTaskSaveDTO.setRiskType("UNAVAILABLE");
                plusTaskSaveDTO.setPercentWorkComplete("0");
                plusTaskSaveDTO.setJobOID(snowflakeIdComponent.getInstance().nextId().toString());
                plusTaskSaveDTO.setHealthStatusType("UNAVAILABLE");
                plusTaskSaveDTO.setControlled("0");
                plusTaskSaveDTO.setMarkForDelete("0");
                plusTaskSaveDTO.setEffortDriven("0");

                plusTaskSaveDTO.setOwnerOID(TyAccountContext.getUser().getOid().toString());
                plusTaskSaveDTO.setExecutorOID(TyAccountContext.getUser().getOid().toString());
                BigInteger ownerGroupOid = rtProjectMapper.selectGroupById(typpmProjectDTO.getOid());
                plusTaskSaveDTO.setOwnerGroupOid(ownerGroupOid.toString());
                plusTaskSaveDTO.setExecutorGroupOid(ownerGroupOid.toString());

                String lateFinish = rtProjectServiceImpl.formatLocalDateTime(LocalDateTime.parse(
                        Objects.requireNonNull(ExcelParser.getProjectEndDateWithTime(entry.getValue().get(size).getPlannedEndTime())),
                        WorkdayCalculator.DATE_TIME_FORMATTER));
                plusTaskSaveDTO.setLateStart(rtProjectServiceImpl.formatLocalDateTime(WorkdayCalculator.calculateLateStartFromMillis(LocalDateTime.parse(lateFinish,WorkdayCalculator.DATE_TIME_FORMATTER),durationMillis)));
                plusTaskSaveDTO.setLateFinish(lateFinish);

                plusTaskSaveDTO.setTypeOID("264465053392879616");
                plusTaskSaveDTO.setTypeOTYPE(TableTypeConstrant.TY_TYPE_OTYPE);

                plusTaskSaveDTOS.add(plusTaskSaveDTO);
            }


            this.ganttChartService.saveTableTreeEx(plan.getOid(), plusTaskSaveDTOS);

//            List<ActiveTreeDTO> activeTreeDTOS = this.activeTreeDTOConvert.transList(plusTaskSaveDTOS);
//            for (ActiveTreeDTO activeTreeDTO : activeTreeDTOS) {
//                TyppmActiveTreeDTO map1 = beanMappers.map(activeTreeDTO, TyppmActiveTreeDTO.class);
//                map1.setDoneEffortMillis(0L);
//                map1.setRootOID(plan.getOid());
//                map1.setRootOTYPE(plan.getOtype());
//                map1.setDuration(activeTreeDTO.getDuration());
//                map1.setDurationMillis(activeTreeDTO.getDuration());
//                map1.setRatedHours(0L);
//                this.planActiveService.insertPlanActive(map1);
//            }
        }


    }




}
